package test.designmode.delegatecomm;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


/**
 * @brief  演示的观察者模式分为2种:
 *                  1. 类+反射: 高度模仿委托, 解耦效果好; 
 *                             slot的注册和Qt很相似, 提供一个对象和这个对象的方法名就行;
 *                             
 *                  2. 接口:   标准的观察者模式, 解耦效果一般;
 *                            slot的注册得另外提供一个实现了该接口的实现类的对象; (直接new个匿名类最简单)
 *
 *         此时CommPortBase扮演的是一个Notifier
 */
public class CommPortBase {

    private List<MessageOccuredEventHandler> commMessageOccuredDNListeners = new ArrayList<>();
    private List<FrameSentReceivedEventHandler> frameReceivedDNListeners = new ArrayList<>();
    private List<Frame4Java8EventHandler> frame4Java8DNListeners = new ArrayList<>();

    /**
     * @brief 注册事件处理, 给别人用的
     * @param eventHandler
     */
    public void addMessageOccuredEventListener(MessageOccuredEventHandler eventHandler) {
        this.commMessageOccuredDNListeners.add(eventHandler);
    }

    public void removeMessageOccuredEventListener(MessageOccuredEventHandler eventHandler) {
        this.commMessageOccuredDNListeners.remove(eventHandler);
    }
    
    public void addFrameSentReceivedEventHandler(FrameSentReceivedEventHandler eventHandler) {
        this.frameReceivedDNListeners.add(eventHandler);
    }

    public void removeFrameSentReceivedEventHandler(FrameSentReceivedEventHandler eventHandler) {
        this.frameReceivedDNListeners.remove(eventHandler);
    }
    
    public void addFrame4Java8EventHandler(Frame4Java8EventHandler eventHandler) {
        this.frame4Java8DNListeners.add(eventHandler);
    }

    /**
     * @brief 遍历所有的MessageOccuredEventHandler并执行事件处理
     *        其实完全可当做是一个signal---> void messageOccurSignal(QString msg)
     *        调用了callEventMessageOccured就等价于发送信号: emit messageOccurSignal("hello");
     *        
     * @param sender 这是shuoGG自己加的, 认为这样更加合理些
     * @param messageStr
     */
    public void callEventMessageOccured(Object sender, String messageStr) {
        try {
            for (Iterator<MessageOccuredEventHandler> dnItr = commMessageOccuredDNListeners.iterator(); dnItr
                    .hasNext();) {
                MessageOccuredEventHandler dnDelegate = (MessageOccuredEventHandler) dnItr.next();
                dnDelegate.dnInvokeDelegate(sender, messageStr);
            }
        } catch (Exception ex) {
            System.out.println("异常");
        }
    }

    /** 传统的观察者模式用的是接口, 上面的采用反射用到的是抽象类
     *  这种模式简单, 代价就是别人想使用必须实现XXXEventHandler接口先
     * @param sender
     * @param frame
     */
    public void callEventFrameSend(Object sender, String frame) {
        for (Iterator<FrameSentReceivedEventHandler> iterator = frameReceivedDNListeners.iterator(); iterator.hasNext();) {
            FrameSentReceivedEventHandler frameHandler = (FrameSentReceivedEventHandler) iterator.next();
            frameHandler.onStringSentEvent(sender, frame);
        }
    }
    
    public void callEventFrameRec(Object sender, String frame) {
        for (Iterator<FrameSentReceivedEventHandler> iterator = frameReceivedDNListeners.iterator(); iterator.hasNext();) {
            FrameSentReceivedEventHandler frameHandler = (FrameSentReceivedEventHandler) iterator.next();
            frameHandler.onStringReceivedEvent(sender, frame);
        }
    }
    
    public void callEventFrameJava8(Object sender, String frame) {
        for (Iterator<Frame4Java8EventHandler> iterator = frame4Java8DNListeners.iterator(); iterator.hasNext();) {
            Frame4Java8EventHandler frameHandler = (Frame4Java8EventHandler) iterator.next();
            frameHandler.onJava8SendEvent(sender, frame);
        }
    }
}

